/**
 * 
 */
package org.pexx.rdm.config;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 
 */
public class RIFTProperties {

	public static final String RIFT_CFG = "rift.cfg";
	public static final String RIFT_CFG_LNK = "rift.cfg.lnk";
	public static final String RIFT_REL_PATH = "/AppData/Roaming/Rift/rift.cfg";
	
	private String riftCfg_path;

	private static final Pattern linePattern = Pattern.compile("(\\w+)\\s?=\\s?(.+)");
	private static final Pattern groupPattern = Pattern.compile("\\[(\\w+)\\]");

	private static final String EOL = "\r\n";
	
	
	private HashMap<String, HashMap<String, String>> data = new HashMap<String, HashMap<String,String>>();
	
	public static void main (String[] args) throws IOException {
		RIFTProperties rp = new RIFTProperties("C:/Users/pexx/AppData/Roaming/Rift");
		rp.open();
		
		System.out.println(rp.getBool("Client", "LogCombatConsole"));
		
		rp.setBool("Client", "LogCombatConsole", ! rp.getBool("Client", "LogCombatConsole"));
		
		rp.save();
	
	}
	
	
	/**
	 * @param rift_path
	 */
	public RIFTProperties(String rift_path) {
		
		if (new File (rift_path + RIFT_CFG).exists())
			this.riftCfg_path = (formatPath(rift_path)  + RIFT_CFG);
		else
			this.riftCfg_path = (System.getProperty("user.home") + RIFT_REL_PATH);
	}
	
	public static String formatPath (String path) {
		path = path.trim();
		
		if (!path.endsWith("/") && !path.endsWith("\\"))
			path += "/";
		
		return path;
	}
	
	
	/**
	 * @return the riftRelPath
	 */
	public String getRiftCfgPath() {

		return riftCfg_path;
	}
	
	public void open () throws IOException {
		
		scan ();
			
	}
	
	public void save () throws IOException {
		saveStringToFile(serializeData(), new File (riftCfg_path), false);
	}

	private void scan () throws IOException { // rift_path + RIFT_CFG

		data.clear();
		
		RandomAccessFile rf = new RandomAccessFile(riftCfg_path, "r");
		
		String l;
		Matcher mg, ml;
		
		String group = "";
		
		while (((l = rf.readLine()) != null)) {
			mg = groupPattern.matcher(l);
			ml = linePattern.matcher(l);
			
			if (mg.matches())
				group = mg.group(1);
			
			if (ml.matches())
				getOrCreateGroup(group).put(ml.group(1), ml.group(2));
			
		}
		
		rf.close();
	}
	
	public Set<String> getGroups () {
		return data.keySet();
	}
		
	
	public HashMap<String, String> getProperties (String group) {
		return data.get(group);
	}
	
	public HashMap<String, String> getProperties () {
		
		HashMap <String, String> ret = new HashMap<String, String>();
		
		for (String group : getGroups()) 
			ret.putAll(data.get(group));		
		
		return ret;
	}
	
	public void setProperty (String group, String key, String value) {
		getOrCreateGroup(group).put(key, value);
	}
	
	public void setInt (String group, String key, int value) {
		getOrCreateGroup(group).put(key, "" + value);
	}
	
	public void setDbl (String group, String key, double value) {
		getOrCreateGroup(group).put(key, "" + value);
	}
	
	public void setBool (String group, String key, boolean value) {
		getOrCreateGroup(group).put(key, value ? "True" : "False");
	}
	
	public String getProperty (String group, String key) {
		HashMap<String, String> g = data.get(group);		
		return g == null ? null : g.get(key);
	}
	
	public int getInt (String group, String key) {
		return Integer.parseInt(getProperty(group, key));
	}
	
	public double getDbl (String group, String key) {
		return Double.parseDouble(getProperty(group, key));
	}
	
	public boolean getBool (String group, String key) {
		return Boolean.parseBoolean(getProperty(group, key));
	}
	
	/**
	 * @param group
	 * @return 
	 */
	private HashMap<String, String> getOrCreateGroup(String group) {

		if (!data.containsKey(group))
			data.put(group, new HashMap<String, String>());			
			
		return data.get(group);	
		
	}
	
	private String serializeData () {
		
		StringBuffer out = new StringBuffer();
		
		for (String group : getGroups()) {
			
			appendGroup (out, group);			
		
			for (String key : data.get(group).keySet()) 
				appendValue (out, group, key, data.get(group).get(key));
			
			out.append(EOL);
			
		}
		
		return out.toString();
		
	}

	/**
	 * @param out
	 * @param group
	 * @param key
	 * @param string
	 */
	private static void appendValue(StringBuffer out, String group, String key,
			String value) {

		out.append(key);
		out.append(" = ");
		out.append(value);
		out.append(EOL);
				
	}

	/**
	 * @param out
	 * @param group
	 */
	private static void appendGroup(StringBuffer out, String group) {

		out.append('[');
		out.append(group);
		out.append(']');
		out.append(EOL);		
	}


	public static void saveStringToFile(String s, File f, boolean append)
			throws IOException {
		FileWriter fw = new FileWriter(f, append);
		fw.write(s);
		fw.close();
	}
	
	
}
